<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>proxy实例的set方法</title>
</head>
<body>
  <script>
    // 下面是set方法第四个参数的例子。
    const handler = {
      set: function(obj, prop, value, receiver) {
        obj[prop] = receiver;
        return true
      }
    };
    const proxy = new Proxy({}, handler) // 对空对象进行拦截，handler定义拦截行为
    proxy.foo = 'bar';
    proxy.foo === proxy; // true
    /**
     * 上面代码中，set方法的第四个参数，指的是原始的操作行为所在的那个对象，一般情况下是proxy实例本身
    */
    const handler1 = {
      set: function(obj, prop, value, receiver) {
        obj[prop] = receiver;
        return true
      }
    };
    const proxy1 = new Proxy({}, handler1) // 对空对象进行拦截，handler定义拦截行为
    const myObj = {};
    Object.setPrototypeOf(myObj, proxy); // 给myObj设置原型对象
    // Object.setPrototypeOf() 方法作用与__proto__相同，用来设置一个对象的原型对象(prototype)
    // 返回参数对象本身，它是ES6正式推荐的设置原型对象的方法。
    // 格式
    // Object.setPrototypeOf(obj, prototype);
    myObj.foo = 'bar';
    myObj.foo === myObj // true
    /**
     * 上面代码中，设置myObj.foo属性的值时，myObj并没有foo属性，因此引擎会到myObj的原型链上去找foo属性。
     * myObj的原型对象proxy1是一个Proxy实例，设置它的foo属性会触发代理handler1的set方法，第四个参数
     * receiver就指向原始赋值行为，所在的对象myObj。
     *
     * 注意： 如果目标对象自身某个属性不可写，那么set方法将不起作用。
    */
   const obj = {};
   Object.defineProperty(obj, 'foo', {
     value: 'bar',
     writable: false
   });
   // 上面代码在obj中定义了一个属性foo 值为bar 只可读不可写，
   const handler2 = {
     set: function(obj, prop, value, receiver) {
       obj[prop] = 'baz';
       // set代理应该返回一个布尔值。严格模式下只能返回true，否则会报错
       return true;
     }
   };
   const proxy2 = new Proxy(obj, handler2);
   proxy2.foo = 'baz';// 直接报错，无法修改值
  //  console.log('proxy2.foo', proxy2.foo)
  </script>
</body>
</html>